package org.openeccos.dao;

import java.io.Serializable;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.openeccos.model.IRoleName;
import org.openeccos.model.MBase;
import org.openeccos.model.MTask;
import org.openeccos.model.MUser;
import org.openeccos.model.MUserRole;

import com.sas.framework.expojo.RepositoryComponent;
import com.sas.framework.expojo.hibernate.HibernatePersistenceProvider;

public class EccosRepository extends RepositoryComponent {
	
	public static final String NAME = "EccosRepository";
	public String getName() { return NAME; }

	public List<MUser> findUserByRole(IRoleName roleName) {
		Query query = getSession().createQuery("SELECT userRef FROM MUserRole up WHERE up.role.name =:name AND up.userRef.login IS NOT NULL");
		query.setParameter("name", roleName);
		return query.list();
	}

	public boolean isUserDeleteable() {
		Query query = getSession().createQuery("SELECT u.id FROM MDistrictAssign AS u WHERE u.userRef=:u");
		query.setParameter("u", this);
		if (!query.list().isEmpty()) {
			return false;
		}

		query = getSession().createQuery("SELECT t.id FROM MTask AS t WHERE t.assignedUser=:u OR t.createdBy=:u OR t.doneBy=:u");
		query.setParameter("u", this);
		if (!query.list().isEmpty()) {
			return false;
		}

		query = getSession().createQuery("SELECT d.id FROM MDiscussionMessage AS d WHERE d.author=:u");
		query.setParameter("u", this);
		if (!query.list().isEmpty()) {
			return false;
		}

		query = getSession().createQuery("SELECT h.id FROM MActivity AS h WHERE h.userRef=:u");
		query.setParameter("u", this);
		if (!query.list().isEmpty()) {
			return false;
		}

		return true;
	}
	
	public MUser findUserByLogin(String login, String password) {
		Criteria criteria = getSession().createCriteria(MUser.class);
		if (password == null || password.trim().length() == 0) {
			criteria.add(Restrictions.eq("invitationCode", login));
		} else {
			criteria.add(Restrictions.eq("login", login));
			criteria.add(Restrictions.eq("password", password));
			criteria.add(Restrictions.eq("active", true));
		}
		MUser user = (MUser)criteria.uniqueResult();
		if (user != null) {
			//eager-load all roles/privileges
			for (MUserRole ur : user.getRoles()) {
				Hibernate.initialize(ur.getRole().getPrivileges());
			}
		}
		return user;
	}

	public boolean hasRole(MUser user, IRoleName roleName) {
		Criteria criteria = getSession().createCriteria(MUserRole.class);
		criteria.createCriteria("role").add(Restrictions.eq("name", roleName.toString()));
		criteria.add(Restrictions.eq("userRef", this));
		List list = criteria.list(); 
		return list.size() > 0;
	}

	public boolean loginExist(String text) {
		Criteria criteria = getSession().createCriteria(MUser.class);
		criteria.add(Restrictions.eq("login", text));
		criteria.setProjection(Projections.id());
		return criteria.list().size() > 0;
	}


	private Session getSession() {
		HibernatePersistenceProvider hpp = (HibernatePersistenceProvider)modelExposer.getPersistenceProvider();
		return hpp.getSession();
	}

	public Object loadById(Class clazz, Serializable id) {
		return getSession().load(clazz, id);
	}

	public MBase getFirst(Class clazz) {
		Criteria criteria = getSession().createCriteria(clazz);
		criteria.setMaxResults(1);
		return (MBase)criteria.uniqueResult();
	}

	public List listAll(Class clazz) {
		Criteria criteria = getSession().createCriteria(clazz);
		return criteria.list();
	}

	public List findCurrentTasks() {
		Criteria criteria = getSession().createCriteria(MTask.class);
		criteria.add(Restrictions.isNull("doneDate"));
		return criteria.list();
	}
}